#pragma once

// TODO: move the enum definitions inside class?

// Represents display attributes of a character. Blink and bold are the only ones supported by CGA.
enum DisplayAttribute
{
    Blink = 128,
    Bold = 8,
    Inverse = 1,
    Underline = 2
};

// Represents all the 8 logical ANSI colors. Actual mapping to physical color is up to the terminal.
enum AnsiColor
{
    Black = 0,
    Red = 1,
    Green = 2,
    Yellow = 3,
    Blue = 4,
    Magenta = 5,
    Cyan = 6,
    White = 7
};

struct CharAttribute
{
    wchar_t Character;
    AnsiColor Foreground;
    AnsiColor Background;
    unsigned char Attributes;

public:
	CharAttribute()
		: Character(L' '), Foreground(White), Background(Black), Attributes(0)
	{
	}

	CharAttribute(wchar_t ch, AnsiColor fg, AnsiColor bg, unsigned char attr)
		: Character(ch), Foreground(fg), Background(bg), Attributes(attr)
	{
	}

	CharAttribute(wchar_t ch)
		: Character(ch), Foreground(White), Background(Black), Attributes(0)
	{
	}
};

class CFrameBuffer
{
public:
	CFrameBuffer(void);
	~CFrameBuffer(void);

	const CharAttribute& operator() (int row, int column) const;
	void CreateBuffer (int rows, int columns);
	void SetCharAttributeAt (int row, int column, CharAttribute c);
	void ScrollUp ();
	void InsertLine (int row);

	static bool HasBold(unsigned char attributes);
	static bool HasBlink(unsigned char attributes);
	static bool HasInverse(unsigned char attributes);
	static bool HasUnderline(unsigned char attributes);

protected:
	static CharAttribute Blank;

	int rows, columns;
    CharAttribute** buffer;

	void FreeBuffer();
};
